using System;
using System.Collections.Generic;
using System.Text;
using Deepcode.Flux.Core.Services.FluxClient;
using Deepcode.Flux.Core.Services.Security;
using Deepcode.Flux.Core.Systems.Registry;
using Deepcode.Flux.Core.Systems.Audit;

namespace Deepcode.Flux.Core.UI
{
	/// <summary>
	/// The AdministrationModulePage class is a base class for creating Flux.NET integrated
	/// pages. It integrates to roles based security, has optional scrollbar positional tracking
	/// and automatically includes the appropriate stylesheets on the page.
	/// </summary>
	public class AdministrationModulePage : System.Web.UI.Page
	{
		/// <summary>
		/// Provides a useful property that will output a required indicator - a red asterix
		/// </summary>
		public virtual string Required { get { return "<font color=red>*</font>"; } }
		/// <summary>
		/// Override this to specify the permission code that is needed to execute this administration module.
		/// If the user does not have the permission code associated they will be kicked from the system. 
		/// In windows authentication mode, if the user has authenticated, but is not in the Flux
		/// user lists, they will be kicked also.
		/// </summary>
		public virtual string RequiredPermissionCode { get { return ""; } }
		/// <summary>
		/// Override this and change it to return true to force the module page to
		/// check whether or not Flux has been installed before it does anything else.
		/// If Flux has not been installed, it will then open the /Setup scripts to
		/// install it. Generally leave the base implementation to just return false.
		/// </summary>
		public virtual bool CheckFluxConfiguredOnStart { get { return false; } }

		#region Scrollbar tracking
		/// <summary>
		/// Internal property determining if the page has scrollbar tracking enabled
		/// between postbacks. On is the default, which will ensure that the page remains
		/// in it's existing scroll position during postbacks. To turn off this behaviour
		/// override HasScrollbarTracking and return false;
		/// </summary>
		protected virtual bool HasScrollbarTracking { get { return true; } }
		// Private fields to hold last know scroll position
		private string _LastKnownScrollX = "0";
		private string _LastKnownScrollY = "0";
		// Properties to interrogate last known scroll position - for passing around forms etc
		protected string LastKnownScrollX { get { return _LastKnownScrollX; } }
		protected string LastKnownScrollY { get { return _LastKnownScrollY; } }
		/// <summary>
		/// EnableScrollbarTracking will add all of the necessary code etc to allow
		/// scrollbars to be tracked between postbacks.
		/// </summary>
		protected void EnableScrollbarTracking()
		{
			// Ensure we've got postback code
			Page.ClientScript.GetPostBackEventReference( this, "" );

			// Register the hijacking code to replace __doPostBack with out own
			Page.ClientScript.RegisterClientScriptInclude(
				this.GetType(),
				"Deepcode.Flux.Core.UI.AdministrationModulePage.SCROLLBARHIJACK",
				ClientHelper.GetFluxClientFile("ScrollRestorePage/HijackPostback.js"));

			if (!Page.IsPostBack)
			{
				// See if we have a URL parameter for setting the scrollbar position
				string ImplicitScrollState = Request["ScrollTo"];
				if ((ImplicitScrollState != null) && (ImplicitScrollState != ""))
				{
					// Split the field value against the comma to obtain X and Y
					string[] LoadScrollStates = ImplicitScrollState.Split(',');
					if (LoadScrollStates.Length < 2)
						throw new Exception("INVALID ScrollTo URL Parameter");

					// Store them into the property fields
					_LastKnownScrollX = LoadScrollStates[0];
					_LastKnownScrollY = LoadScrollStates[1];
				}
			}
			else
			{
				// See if we already have a scroll bar state
				string LastScrollState = Request["__SCROLLBARSTATE"];
				if ((LastScrollState != null) && (LastScrollState != ""))
				{
					// Split the field value against the comma to obtain X and Y
					string[] LoadScrollStates = LastScrollState.Split(',');
					if (LoadScrollStates.Length < 2)
						throw new Exception("INVALID __SCROLLBARSTATE");

					// Store them into the property fields
					_LastKnownScrollX = LoadScrollStates[0];
					_LastKnownScrollY = LoadScrollStates[1];
				}
			}

			// Register the hidden field to store the current scrollbar state
			Page.ClientScript.RegisterHiddenField("__SCROLLBARSTATE", String.Format("{0},{1}", _LastKnownScrollX, _LastKnownScrollY));
		}
		#endregion
		#region OnInit 
		/// <summary>
		/// OnInit event handler adds script for standard admin module styles and also
		/// enables the scrollbar tracking scripts where necessary.
		/// </summary>
		/// <param name="e"></param>
		protected override void OnInit(EventArgs e)
		{
			// Perform default initialisation
			base.OnInit(e);
			
			// Register the stylesheets for administration
			Page.ClientScript.RegisterClientScriptBlock( 
				this.GetType(),
				"StandardStylesheet",
				String.Format("<link rel=\"stylesheet\" href=\"{0}\" />", 
					Page.ResolveClientUrl("~/admin/asset/style/GeneralStyle.css")));

			// Add Scrollbar tracking
			if( HasScrollbarTracking ) EnableScrollbarTracking();
		}
		#endregion
		#region OnLoad
		/// <summary>
		/// OnLoad event sets the cacheability of the module page to not cacheable.
		/// Next, the code checks to ensure that Flux is configured and if not redirects
		/// to the installation scripts.
		/// In addition the system then checks to ensure that the user has the appropriate
		/// permission to access this module, as degined in RequiredPermissionCode. If the 
		/// user is not authenticated with the code provided, an error is raised.
		/// </summary>
		/// <param name="e"></param>
		protected override void OnLoad(EventArgs e)
		{
			// Turn off all caching
			this.Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
			// Ensure Flux is setup if need be
			if (CheckFluxConfiguredOnStart)
			{
				if (!System.IO.File.Exists(Server.MapPath("~/Settings/Flux.config")))
					Response.Redirect("~/admin/Setup/Install/default.aspx", true);
			}
			// Check the user has the permission code any permission code will do, 
			// even if blank - as we need to ensure they are in the user's table.
			if( ! AdministrationSecurity.UserHasPermission(RequiredPermissionCode))
			{
				Deepcode.Flux.Core.Services.Errors.ErrorService es = new Deepcode.Flux.Core.Services.Errors.ErrorService();
				es.DoError(Deepcode.Flux.Core.Services.Errors.StandardError.NOT_AUTHORISED);
				return;
			}

			// Check lic key as necessary
			//Deepcode.Flux.Services.LicService.Licence.IsLicencedHere();

			// Continue standard processing
			base.OnLoad(e);
		}
		#endregion
		#region GetAttribute functionality
		/// <summary>
		/// Returns the value of the URL/FORM attribute as specified by
		/// AttributeName. If this attribute isn't passed, is null, or is 
		/// empty, the DefaultValue is returned.
		/// </summary>
		/// <param name="AttributeName"></param>
		/// <param name="DefaultValue"></param>
		/// <returns></returns>
		protected virtual string GetAttribute(string AttributeName, string DefaultValue)
		{
			string v = Request[AttributeName];
			if ((v == null) || (v == "")) return DefaultValue;
			return v;
		}
		/// <summary>
		/// Returns the value of the URL/FORM attribute as specified by
		/// AttributeName. If this attribute isn't passed, is null,
		/// is empty, or cannot be converted to an int, the DefaultValue
		/// is returned instead.
		/// </summary>
		/// <param name="AttributeName"></param>
		/// <param name="DefaultValue"></param>
		/// <returns></returns>
		protected virtual int GetAttribute(string AttributeName, int DefaultValue)
		{
			string v = GetAttribute(AttributeName, DefaultValue.ToString());
			try
			{
				return Int32.Parse(v);
			}
			catch
			{
				return DefaultValue;
			}
		}
		#endregion
		#region User Setting functionality
		/// <summary>
		/// Loads a user setting from the registry, under the current user's /General
		/// branch. See FluxRegistry object for more information about the 
		/// registry and what can be stored there.
		/// </summary>
		/// <param name="Key"></param>
		/// <param name="Default"></param>
		/// <returns></returns>
		protected virtual int UserSetting( string Key, int Default )
		{
			FluxRegistry r = new FluxRegistry(FluxRegistryRoot.CURRENT_USER, "/General");
			return r.GetKey(Key, Default);
		}
		/// <summary>
		/// Loads a user seting from the registry, under the branch specified.
		/// </summary>
		/// <param name="Branch"></param>
		/// <param name="Key"></param>
		/// <param name="Default"></param>
		/// <returns></returns>
		protected virtual int UserSetting(string Branch, string Key, int Default)
		{
			FluxRegistry r = new FluxRegistry(FluxRegistryRoot.CURRENT_USER, Branch);
			return r.GetKey(Key, Default);
		}
		/// <summary>
		/// Loads a user setting from the registry, under the current user's /General
		/// branch. See FluxRegistry object for more information about the 
		/// registry and what can be stored there.
		/// </summary>
		/// <param name="Key"></param>
		/// <param name="Default"></param>
		/// <returns></returns>
		protected virtual bool UserSetting( string Key, bool Default )
		{
			FluxRegistry r = new FluxRegistry(FluxRegistryRoot.CURRENT_USER, "/General");
			return r.GetKey(Key, Default);
		}
		/// <summary>
		/// Loads a user setting from the registry, under the branch specified.
		/// </summary>
		/// <param name="Branch"></param>
		/// <param name="Key"></param>
		/// <param name="Default"></param>
		/// <returns></returns>
		protected virtual bool UserSetting(string Branch, string Key, bool Default)
		{
			FluxRegistry r = new FluxRegistry(FluxRegistryRoot.CURRENT_USER, Branch);
			return r.GetKey(Key, Default);
		}
		/// <summary>
		/// Loads a user setting from the registry, under the current user's /General
		/// branch. See FluxRegistry object for more information about the 
		/// registry and what can be stored there.
		/// </summary>
		/// <param name="Key"></param>
		/// <param name="Default"></param>
		/// <returns></returns>
		protected virtual string UserSetting( string Key, string Default )
		{
			FluxRegistry r = new FluxRegistry(FluxRegistryRoot.CURRENT_USER, "/General");
			return r.GetKey(Key, Default);
		}
		/// <summary>
		/// Loads a user setting from the registry, under the branch specified.
		/// </summary>
		/// <param name="Branch"></param>
		/// <param name="Key"></param>
		/// <param name="Default"></param>
		/// <returns></returns>
		protected virtual string UserSetting(string Branch, string Key, string Default)
		{
			FluxRegistry r = new FluxRegistry(FluxRegistryRoot.CURRENT_USER, Branch);
			return r.GetKey(Key, Default);
		}
		/// <summary>
		/// Set a user setting to the registry under the current user's /General branch.
		/// </summary>
		/// <param name="Key"></param>
		/// <param name="Value"></param>
		protected virtual void SetUserSetting( string Key, int Value )
		{
			FluxRegistry r = new FluxRegistry(FluxRegistryRoot.CURRENT_USER, "/General");
			r.SetKey( Key, Value );
		}
		/// <summary>
		/// Set a user setting under the specified branch within the current user's branch
		/// </summary>
		/// <param name="Branch"></param>
		/// <param name="Key"></param>
		/// <param name="Value"></param>
		protected virtual void SetUserSetting(string Branch, string Key, int Value)
		{
			FluxRegistry r = new FluxRegistry(FluxRegistryRoot.CURRENT_USER, Branch);
			r.SetKey( Key, Value );
		}
		/// <summary>
		/// Set a user setting to the registry under the current user's /General branch.
		/// </summary>
		/// <param name="Key"></param>
		/// <param name="Value"></param>
		protected virtual void SetUserSetting( string Key, bool Value )
		{
			FluxRegistry r = new FluxRegistry(FluxRegistryRoot.CURRENT_USER, "/General");
			r.SetKey( Key, Value );
		}
		/// <summary>
		/// Set a user setting under the specified branch under the current user's branch
		/// </summary>
		/// <param name="Branch"></param>
		/// <param name="Key"></param>
		/// <param name="Value"></param>
		protected virtual void SetUserSetting(string Branch, string Key, bool Value)
		{
			FluxRegistry r = new FluxRegistry(FluxRegistryRoot.CURRENT_USER, Branch);
			r.SetKey( Key, Value );
		}
		/// <summary>
		/// Set a user setting to the registry under the current user's /General branch.
		/// </summary>
		/// <param name="Key"></param>
		/// <param name="Value"></param>
		protected virtual void SetUserSetting( string Key, string Value )
		{
			FluxRegistry r = new FluxRegistry(FluxRegistryRoot.CURRENT_USER, "/General");
			r.SetKey( Key, Value );
		}
		/// <summary>
		/// Set a user setting under the secified branch under the current user's branch
		/// </summary>
		/// <param name="Branch"></param>
		/// <param name="Key"></param>
		/// <param name="Value"></param>
		protected virtual void SetUserSetting(string Branch, string Key, string Value)
		{
			FluxRegistry r = new FluxRegistry(FluxRegistryRoot.CURRENT_USER, Branch);
			r.SetKey( Key, Value );
		}
		#endregion
		#region Current User information
		/// <summary>
		/// Private field holding the cache of the current administration user
		/// </summary>
		private AdministrationSecuritySession CacheCurrentUser = null;
		/// <summary>
		/// Indicator whether current user has been loaded or not
		/// </summary>
		private bool LoadedCacheCurrentUser = false;
		/// <summary>
		/// Returns the current user session (could be null)
		/// </summary>
		protected AdministrationSecuritySession CurrentUser
		{
			get
			{
				if (!LoadedCacheCurrentUser)
					CacheCurrentUser = AdministrationSecurity.GetSession();

				return CacheCurrentUser;
			}
		}
		#endregion
	}
}
